package com.hbnrtech.sip.gb28181.listener;

import com.hbnrtech.sip.gb28181.handler.CatalogResponseHandler;
import com.hbnrtech.sip.gb28181.handler.SipKeepAliveHandler;
import com.hbnrtech.sip.gb28181.handler.SipRegisterHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sip.*;
import javax.sip.header.CallIdHeader;
import javax.sip.header.Header;
import javax.sip.header.ToHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

/**
 * @author liuduo
 * @date 2025-04-21 10:53
 */

@Component
@Slf4j
public class SipListenerImpl implements SipListener {

    @Autowired
    private SipRegisterHandler registerHandler; // 注册处理器
    @Autowired
    private SipKeepAliveHandler keepAliveHandler; // 心跳处理器
    @Autowired
    private MessageFactory messageFactory;
    @Autowired
    private CatalogResponseHandler catalogResponseHandler;

    @Override
    public void processRequest(RequestEvent requestEvent) {
        Request request = requestEvent.getRequest();
        String method = request.getMethod();
        Header callIdHeader = request.getHeader(CallIdHeader.NAME);
        log.info("<<< Received SIP Request: Method = {}, {}, {}, {}",
                method,
                request.getHeader(javax.sip.header.FromHeader.NAME),
                request.getHeader(javax.sip.header.ToHeader.NAME),
                callIdHeader);
        log.trace("Full Request:\n{}", request);

        // 统一获取或创建事务
        ServerTransaction serverTransaction = requestEvent.getServerTransaction();
        SipProvider sipProvider = (SipProvider) requestEvent.getSource();
        if (serverTransaction == null) {
            try {
                // 确定使用哪个 Provider (这里简化，用默认的)
                serverTransaction = sipProvider.getNewServerTransaction(request);
                log.debug("Created new ServerTransaction {} for request.", serverTransaction.getBranchId());
            } catch (TransactionUnavailableException | TransactionAlreadyExistsException e) {
                log.error("Could not get or create server transaction for request.", e);
                // 无法处理，也无法可靠响应，直接返回
                return;
            }
        } else {
            log.debug("Using existing ServerTransaction {} for request.", serverTransaction.getBranchId());
        }

        try {
            // 处理 REGISTER 请求
            if (Request.REGISTER.equals(method)) {
                log.info("Handling Register request ({})...", callIdHeader);
                registerHandler.handleRegister(requestEvent, serverTransaction);
            } else if (Request.MESSAGE.equals(method)) {
                String rawContent = new String(request.getRawContent());
                // 处理心跳请求
                if (rawContent.contains("<CmdType>Keepalive</CmdType>")) {
                    log.info("Handling Keepalive request ({})...", callIdHeader);
                    keepAliveHandler.handleKeepAlive(requestEvent, serverTransaction);
                }
                // 简单判断是否是 Catalog 响应 (更可靠的方式是解析 CmdType)
                if (rawContent.contains("<CmdType>Catalog</CmdType>") && rawContent.contains("<Response>")) {
                    log.info("Handling Catelog Response ({})...", callIdHeader);
                    // 异步处理，避免阻塞 SIP 监听线程
                    ServerTransaction finalServerTransaction = serverTransaction;
                    CompletableFuture.runAsync(() -> {
                        catalogResponseHandler.handleCatalogResponse(rawContent, requestEvent, finalServerTransaction);
                    }).exceptionally(e -> {
                        log.error("Async Catalog response processing failed for: {}", callIdHeader);
                        return null;
                    });
                }
            }
            // 其他方法如 INVITE, ACK, BYE, CANCEL, OPTIONS 等根据需要处理
            else {
                log.warn("Received unhandled SIP method: {}", method);
                // 使用获取到的事务发送错误响应
                sendServerErrorResponse(Response.METHOD_NOT_ALLOWED, request, serverTransaction, "Method Not Allowed");
            }
        } catch (Exception e) {
            log.error("Error processing SIP request", e);
            // 在异常处理中也使用同一个事务
            sendServerErrorResponse(Response.SERVER_INTERNAL_ERROR, request, serverTransaction, "Failed to process " + method + ": " + e.getMessage());
        }
    }

    @Override
    public void processResponse(ResponseEvent responseEvent) {
        Response response = responseEvent.getResponse();
        log.info(">>> Received SIP Response: Status={}, CSeq={}, CallId={}",
                response.getStatusCode(),
                response.getHeader(javax.sip.header.CSeqHeader.NAME),
                response.getHeader(javax.sip.header.CallIdHeader.NAME));
        log.trace("Full Response:\n{}", response);
        // 在注册场景，服务器主要是接收请求，较少处理响应
        // 如果平台也作为 UAC 发起请求（如向上级注册），则需要处理这里的响应
    }

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        log.warn("SIP Timeout event: Transaction={}, IsServerTransaction={}",
                timeoutEvent.isServerTransaction() ? timeoutEvent.getServerTransaction() : timeoutEvent.getClientTransaction(),
                timeoutEvent.isServerTransaction());
        // 处理请求超时或响应超时
    }

    @Override
    public void processIOException(IOExceptionEvent ioExceptionEvent) {
        log.error("SIP IO Exception: Host={}, Port={}, Transport={}",
                ioExceptionEvent.getHost(), ioExceptionEvent.getPort(), ioExceptionEvent.getTransport());
        // 处理网络层面错误

        log.error(ioExceptionEvent.toString());
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
        log.debug("SIP Transaction Terminated event: Transaction={}, IsServerTransaction={}",
                transactionTerminatedEvent.isServerTransaction() ? transactionTerminatedEvent.getServerTransaction() : transactionTerminatedEvent.getClientTransaction(),
                transactionTerminatedEvent.isServerTransaction());
        // 事务结束（完成或超时）
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        log.debug("SIP Dialog Terminated event: Dialog={}", dialogTerminatedEvent.getDialog());
        // 对话结束 (通常由 BYE 或超时引起)
    }

    private void sendServerErrorResponse(int statusCode, Request request, ServerTransaction serverTransaction, String reason) {
        try {
            Response response = messageFactory.createResponse(statusCode, request);
            if (reason != null && !reason.isEmpty()) {
                response.setReasonPhrase(reason);
            }

            ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
            if (toHeader != null && toHeader.getTag() == null) {
                toHeader.setTag(UUID.randomUUID().toString());
            } else if (toHeader == null) {
                log.error("To header is missing in the generated {} response.", statusCode);
            }

            serverTransaction.sendResponse(response);
            log.info(">>> Sent {} {} response.", statusCode, reason);
        } catch (Exception ex) {
            String txId = (serverTransaction != null) ? serverTransaction.getBranchId() : "N/A";
            log.error("Failed to send {} response using transaction {}.", statusCode, txId, ex);
        }
    }
}
